$.unparam = function (value) {
    if (value){
        var
        params = {},
        pieces = value.split('&'),
        pair, i, l;
        for (i = 0, l = pieces.length; i < l; i++) {
            pair = pieces[i].split('=', 2);
            params[pair[0]] = (pair.length == 2 ? pair[1].replace(/\+/g, ' ') : true);
        }
    }
	else {
        params = false;
    }

    return params;
}; 

$.fn.GtGrid = function(options) {
    var isto = this;
    var opts = $.extend({},$.fn.GtGrid.defaults,options);
	var objDataCache = {};
    var html = '';
    var namespace = 'GtGrid'+isto[0].id;
	var numeroPaginacao;
	var totalPage;
	var paginaAtual;

    GtCookie = {
        criar: function(name,value,days) {

            var expires;

            if (days) {
                var date = new Date();
                date.setTime(date.getTime()+(days*24*60*60*1000));
                expires = "; expires="+date.toGMTString();
            } else {
                expires = "";
            }

            document.cookie = name+"="+value+expires+"; path=/";
        },

        ler: function(name) {

            var nameEQ = name + "=";
            var ca = document.cookie.split(';');

            for (var i=0;i < ca.length;i++) {
                    var c = ca[i];

                    while (c.charAt(0)==' ') {
                        c = c.substring(1,c.length);
                    }

                    if (c.indexOf(nameEQ) == 0) {
                        return c.substring(nameEQ.length,c.length);
                    }
            }

            return null;
        },

        apagar: function(name) {
            GtCookie.criar(name,"",-1);
        }

    }

    var GtGrid = {
        montaTbody: function(response){

            var limite = opts.limite;
            var html = '';
            var classCss, tmp;
			var alinhamento;

            if (response.data) {
                if (response.data.length < opts.limite) {
                    limite = response.data.length;
                }
            }
			else {
                limite = 0;
            }

            if (limite > 0) {

                for (var i = 0; i < limite; i++) {
                    classCss = (i%2 == 0) ? 'claro' : 'escuro';

                    html += '<tr class="'+classCss+'" attr="clicar">';
                    for (var k in response.data[i]) {
						tmp = typeof(opts.colunas[k - 1].alinhamento) != 'undefined' ? opts.colunas[k - 1].alinhamento : null;

						if (tmp == 'centro') 
							alinhamento = 'align="center"';
						else if (tmp == 'direito')
							alinhamento = 'align="right"';
						else
							alinhamento = 'align="left"';
                        html += '<td '+ alinhamento +'>'+response.data[i][k]+'</td>';
                    }
                    html += '</tr>';
                }

            }
			else {
                html += '<tr>';
                html += '<td align="center" colspan='+opts.colunas.length+'>Nenhum Registro Encontrado</td>';
                html += '</tr>';
            }

            $(isto).find('tbody').html(html);
        },

        montaTfoot: function(response, paginaAtual) {

            var html = '';
            paginaAtual    = (paginaAtual) ? paginaAtual : 1;
            response.total = (response.total) ? response.total : 0;

            var limite = opts.limite*paginaAtual;
            if (limite > response.total) {
                limite = response.total;
            }

            var iniPage = paginaAtual-10;
            if (iniPage < 1  ) {
                iniPage = 1
            }

			totalPage = Math.ceil(response.total/opts.limite);

			var inativo_inicial = paginaAtual == 1 ? '-inativo' : '';
			var inativo_final = paginaAtual >= totalPage ? '-inativo' : '';

            html += '<tr>';
            html += '<td colspan="' + (opts.colunas.length) + '" align="center"><div style="width:220px">';
			html += '<div class="gt-icons' + inativo_inicial + ' gt-grid-primeiro"></div>';
			html += '<div class="gt-icons' + inativo_inicial + ' gt-grid-anterior"></div>';
			html += '| P&aacute;gina <input type="text" id="numeroPaginacao" value="' + paginaAtual + '" size="1"> de ' + totalPage + ' |';
			html += '<div class="gt-icons' + inativo_final + ' gt-grid-ultimo"></div>';
			html += '<div class="gt-icons' + inativo_final + ' gt-grid-proximo"></div>';
            html += '</div></td>';
            html += '</tr>';

            $(isto).find('tfoot').html(html);

			numeroPaginacao = $("#numeroPaginacao");
			numeroPaginacao.keypress(function (event) {
				if (event.which == 13) {
					GtGrid.irPagina();
				}
			});

			if (!inativo_inicial) {
				$(".gt-grid-primeiro").click(function(){
					GtGrid.navega("primeiro");
				});

				$(".gt-grid-anterior").click(function(){
					GtGrid.navega("anterior");
				});
			}

			if (!inativo_final) {
				$(".gt-grid-proximo").click(function(){
					GtGrid.navega("proximo");
				});

				$(".gt-grid-ultimo").click(function(){
					GtGrid.navega("ultimo");
				});
			}
        },

        __detectOrder: function(data, cache) {
            var order;

            if (data && data.order) {
                var orderUrl = (cache) ? cache.order.split(' ') : ['1', 'DESC'];
                order = (orderUrl[0] == data.order && orderUrl[1] == 'ASC') ? data.order+' DESC' : data.order+' ASC';
            }
			else {
                order = (cache.order) ? cache.order : '1 ASC';
            }

            $(isto).find('.gt-grid-order-asc, .gt-grid-order-desc').removeClass('gt-grid-order-asc gt-grid-order-desc');

            var orderNow =  order.split(' ');

            if (orderNow[1] == 'ASC') {
				$(isto).find('#gt-grid-order-'+orderNow[0]+' span').addClass('gt-grid-order-asc');
            }
			else {
				$(isto).find('#gt-grid-order-'+orderNow[0]+' span').addClass('gt-grid-order-desc');
            }

            return order;
        },

        __setStorage: function(objData){

            var dataSer = $.param(objData);

            if (opts.cacheUrl) {
                window.location.hash = dataSer;
            }

            if (opts.cacheCookie) {
                GtCookie.criar(namespace, dataSer, 0);
            }

            return dataSer;
        },

		irPagina: function() {
			var tmp = numeroPaginacao.val();
			if (tmp > 0 && tmp <= totalPage)
				GtGrid.reload({pagina:tmp});
		},

		navega: function (local) {

			var tmp = parseInt(numeroPaginacao.val());

			if (local == 'ultimo')
				numeroPaginacao.val(totalPage);
			else if (local == 'anterior')
				numeroPaginacao.val(tmp-1);
			else if (local == 'proximo')
				numeroPaginacao.val(tmp+1);

			else
				numeroPaginacao.val('1');

			GtGrid.irPagina();
		},

        reload: function(data){                        		           

            if (data && data.consultar) {
                for (i in opts.data) {
                    if (opts.data[i].val() != '') {
                        objDataCache[i] = opts.data[i].val();
                    }
					else {
                        delete objDataCache[i];
                    }               
                }

                objDataCache.pagina = 1;
            }

			objDataCache.pagina = (data && data.pagina) ? data.pagina : 1;
            objDataCache.limite = (data && data.limite) ? data.limite : opts.limite;
			objDataCache.order = this.__detectOrder(data, objDataCache);

            var dataSer = this.__setStorage(objDataCache);

            $.ajax({
                url: opts.url,
                type:'get',
                data: dataSer,
                dataType:'json',
                success: function(response) {
                    GtGrid.montaTbody(response);
                    GtGrid.montaTfoot(response, parseInt(objDataCache.pagina));

                    if (data && data.callback) {
                        data.callback(response);
                    }
                }
            });
        }
    }

    html += '<table id="gt-grid-table" class="gt-grid" width="100%" cellpadding="0" cellspacing="0">';
    html += '<thead>';

    for (var i in opts.colunas) {
        html += '<th width="'+opts.colunas[i].largura+'"><span id="gt-grid-order-'+(parseInt(i)+1)+'">'+opts.colunas[i].nome+' <span class="gt-icons"></span></span></th>';
    }

    html += '</thead>';
    html += '<tbody>';
    html += '</tbody>';
    html += '<tfoot>';
    html += '</tfoot>';
    html += '</table>';

    $(this).html(html);

    $(isto).find('thead span[class!="gt-icons"]').each(function(i){
        $(this).bind('click', function(){
			if (opts.colunas[i].ordenar)
				GtGrid.reload({pagina:1,order:(i+1)});
        });
    });

    if (opts.IniReload) {
        var objDataUrl = {consultar:true}, hash = {};

        if (opts.cacheUrl) {
            hash = $.unparam(window.location.hash.substring(1));
        }

        if (hash.gtcookie) {
            var cookieSer = GtCookie.ler(namespace);
            hash = $.unparam(cookieSer);

            if (opts.cacheUrl) {
                window.location.hash = cookieSer;
            }
        }

        for (i in hash) {
            if (hash[i] && $.inArray(i, ['pagina', 'limite', 'order']) == -1 && opts.data[i]) {
                opts.data[i].val(hash[i]);
            }
        }

		if (hash) {
			objDataCache = hash;
		}

        if (hash.pagina) {
            objDataUrl.pagina = hash.pagina;
        }

        if (hash.limite) {
            objDataUrl.limite = hash.limite;
        }

        GtGrid.reload(objDataUrl);
    }
	else {
        GtGrid.montaTbody({data:[]});
        GtGrid.montaTfoot({total:0}, 1);
    }

    return GtGrid;
}

$.fn.GtGrid.defaults = {
    limite: 30
    ,url: ''
    ,colunas : []
    ,data : {}
    ,IniReload : true
    ,cacheUrl: true
    ,cacheCookie: true
};
